import bcryptjs from 'bcryptjs';
import { Types } from 'mongoose';
import { v4 as uuidv4 } from 'uuid';
import { UserDAO } from '../dao/UserDAO';
import { SessionDAO } from '../dao/SessionDAO';
import { IUser } from '../models/user';
import { ISession } from '../models/session';

export interface RegisterData {
  username: string;
  email: string;
  password: string;
  realName: string;
  phone?: string;
  avatar?: string;
  teamId?: Types.ObjectId;
  departmentId?: Types.ObjectId;
  status?: 'active' | 'inactive' | 'disabled';
}

export interface LoginData {
  username?: string;
  email?: string;
  password: string;
  systemId: Types.ObjectId;
  ipAddress: string;
  userAgent: string;
}

export interface UpdateProfileData {
  realName?: string;
  phone?: string;
  avatar?: string;
  teamId?: Types.ObjectId;
  departmentId?: Types.ObjectId;
}

export interface ChangePasswordData {
  currentPassword: string;
  newPassword: string;
}

export interface BatchCreateResult {
  success: boolean;
  users: IUser[];
  successCount: number;
  failureCount: number;
  failures: Array<{
    data: any;
    error: string;
  }>;
  message: string;
}

export interface ServiceResult<T = any> {
  success: boolean;
  data?: T;
  user?: IUser;
  users?: IUser[];
  session?: ISession;
  message: string;
}

export class UserService {
  constructor(
    private userDAO: UserDAO,
    private sessionDAO: SessionDAO
  ) {}

  /**
   * 用户注册
   */
  async register(userData: RegisterData): Promise<ServiceResult<IUser>> {
    try {
      // 验证必填字段
      if (!userData.username || !userData.email || !userData.password) {
        throw new Error('用户名、邮箱和密码为必填字段');
      }

      // 检查用户名是否已存在
      const existingUserByUsername = await this.userDAO.findByUsername(userData.username);
      if (existingUserByUsername) {
        throw new Error('用户名已存在');
      }

      // 检查邮箱是否已存在
      const existingUserByEmail = await this.userDAO.findByEmail(userData.email);
      if (existingUserByEmail) {
        throw new Error('邮箱已存在');
      }

      // 创建用户数据（密码将由User模型的pre-save钩子自动加密）
      const userCreateData = {
        ...userData,
        status: userData.status || 'active' as const
      };

      // 创建用户
      const user = await this.userDAO.create(userCreateData);

      // 返回结果时不包含密码
      const userResult = {
        ...user.toObject(),
        password: undefined
      };

      return {
        success: true,
        user: userResult as IUser,
        message: '用户注册成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 用户登录
   */
  async login(loginData: LoginData): Promise<ServiceResult<{ user: IUser; session: ISession }>> {
    try {
      let user: IUser | null = null;

      // 根据用户名或邮箱查找用户
      if (loginData.username) {
        user = await this.userDAO.findByUsername(loginData.username);
      } else if (loginData.email) {
        user = await this.userDAO.findByEmail(loginData.email);
      }

      if (!user) {
        throw new Error('用户名或密码错误');
      }

      // 检查用户状态
      if (user.status === 'disabled') {
        throw new Error('用户账户已被禁用');
      }
      
      if (user.status === 'inactive') {
        throw new Error('用户账户未激活');
      }

      // 验证密码
      const isPasswordValid = await bcryptjs.compare(loginData.password, user.password);
      if (!isPasswordValid) {
        throw new Error('用户名或密码错误');
      }

      // 创建会话
      const sessionData = {
        sessionId: uuidv4(),
        userId: user._id as Types.ObjectId,
        systemId: loginData.systemId,
        sessionType: 'master' as const,
        ipAddress: loginData.ipAddress,
        userAgent: loginData.userAgent,
        loginTime: new Date(),
        lastAccessTime: new Date(),
        expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24小时后过期
        isActive: true
      };

      const session = await this.sessionDAO.create(sessionData);

      // 返回结果时不包含密码
      const userResult = {
        ...user.toObject(),
        password: undefined
      };

      return {
        success: true,
        user: userResult as IUser,
        session,
        message: '登录成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 用户登出
   */
  async logout(sessionId: string): Promise<ServiceResult> {
    try {
      // 查找会话
      const session = await this.sessionDAO.findBySessionId(sessionId);
      if (!session) {
        throw new Error('会话不存在或已过期');
      }

      // 删除会话
      await this.sessionDAO.delete(sessionId);

      return {
        success: true,
        message: '登出成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 更新用户资料
   */
  async updateProfile(userId: Types.ObjectId, updateData: UpdateProfileData): Promise<ServiceResult<IUser>> {
    try {
      // 检查用户是否存在
      const existingUser = await this.userDAO.findById(userId);
      if (!existingUser) {
        throw new Error('用户不存在');
      }

      // 过滤敏感字段，只允许更新特定字段
      const allowedFields = ['realName', 'phone', 'avatar', 'teamId', 'departmentId'];
      const filteredUpdateData: any = {};

      for (const [key, value] of Object.entries(updateData)) {
        if (allowedFields.includes(key)) {
          filteredUpdateData[key] = value;
        }
      }

      filteredUpdateData.updatedAt = new Date();

      // 更新用户
      const updatedUser = await this.userDAO.update(userId, filteredUpdateData);

      // 返回结果时不包含密码
      const userResult = {
        ...updatedUser!.toObject(),
        password: undefined
      };

      return {
        success: true,
        user: userResult as IUser,
        message: '用户资料更新成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 修改密码
   */
  async changePassword(userId: Types.ObjectId, changeData: ChangePasswordData): Promise<ServiceResult> {
    try {
      // 检查用户是否存在
      const user = await this.userDAO.findById(userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 验证当前密码
      const isCurrentPasswordValid = await bcryptjs.compare(changeData.currentPassword, user.password);
      if (!isCurrentPasswordValid) {
        throw new Error('当前密码错误');
      }

      // 加密新密码
      const saltRounds = 10;
      const hashedNewPassword = await bcryptjs.hash(changeData.newPassword, saltRounds);

      // 更新密码
      await this.userDAO.update(userId, {
        password: hashedNewPassword,
        updatedAt: new Date()
      });

      return {
        success: true,
        message: '密码修改成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 重置密码
   */
  async resetPassword(userId: Types.ObjectId, newPassword: string): Promise<ServiceResult> {
    try {
      // 检查用户是否存在
      const user = await this.userDAO.findById(userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 加密新密码
      const saltRounds = 10;
      const hashedPassword = await bcryptjs.hash(newPassword, saltRounds);

      // 更新密码
      await this.userDAO.update(userId, {
        password: hashedPassword,
        updatedAt: new Date()
      });

      return {
        success: true,
        message: '密码重置成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 获取用户信息
   */
  async getUserInfo(userId: Types.ObjectId): Promise<ServiceResult<IUser>> {
    try {
      const user = await this.userDAO.findById(userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 返回结果时不包含密码
      const userResult = {
        ...user.toObject(),
        password: undefined
      };

      return {
        success: true,
        user: userResult as IUser,
        message: '获取用户信息成功'
      };
    } catch (error) {
      throw error;
    }
  }

  /**
   * 批量创建用户
   */
  async batchCreateUsers(usersData: RegisterData[]): Promise<BatchCreateResult> {
    const results: IUser[] = [];
    const failures: Array<{ data: any; error: string }> = [];

    for (const userData of usersData) {
      try {
        const result = await this.register(userData);
        if (result.user) {
          results.push(result.user);
        }
      } catch (error) {
        failures.push({
          data: userData,
          error: error instanceof Error ? error.message : '未知错误'
        });
      }
    }

    return {
      success: true,
      users: results,
      successCount: results.length,
      failureCount: failures.length,
      failures,
      message: '批量创建用户完成'
    };
  }

  /**
   * 更新用户状态
   */
  async updateUserStatus(userId: Types.ObjectId, status: 'active' | 'inactive' | 'disabled'): Promise<ServiceResult<IUser>> {
    try {
      // 验证状态值
      const validStatuses = ['active', 'inactive', 'disabled'];
      if (!validStatuses.includes(status)) {
        throw new Error('无效的用户状态');
      }

      // 检查用户是否存在
      const existingUser = await this.userDAO.findById(userId);
      if (!existingUser) {
        throw new Error('用户不存在');
      }

      // 更新用户状态
      const updatedUser = await this.userDAO.updateStatus(userId, status);

      // 返回结果时不包含密码
      const userResult = {
        ...updatedUser!.toObject(),
        password: undefined
      };

      return {
        success: true,
        user: userResult as IUser,
        message: '用户状态更新成功'
      };
    } catch (error) {
      throw error;
    }
  }
}
